/*
 * TMap Designer - A Thematic Map design software
 * Copyright (C) 2006 World Health Organization
 * http://www.who.int
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 */
package who.tmap.imp.impl;

import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import org.apache.log4j.Logger;

import who.tmap.bo.AttrDef;
import who.tmap.bo.Attrs;
import who.tmap.bo.impl.BizObjectFactory;
import who.tmap.common.TMapException;
import who.tmap.imp.ImportAdapterException;
import who.tmap.imp.ODBCDSNLessImportAdapter;

/**
 * @author stl
 *
 * TODO To change the template for this generated type comment go to
 * Window - Preferences - Java - Code Style - Code Templates
 */
public class ODBCDSNLessImportAdapterImpl extends    BaseJDBCAdapterImpl 
									   	  implements ODBCDSNLessImportAdapter {
    
    private static Logger logger = Logger.getLogger(ODBCDSNLessImportAdapterImpl.class);
    // Maximum value for casting a string
    // 4000 is Oracle limit
    private static final int VARCHAR_MAX_SIZE =4000;     
    private static final String JDBC_ODBC_DRIVER_CLASS_NAME ="sun.jdbc.odbc.JdbcOdbcDriver";
  
    protected boolean castString;

         
    public ODBCDSNLessImportAdapterImpl() {
        setName( "ODBC DSN Less" );
    }

    public void configure(Map<String, String> config) throws TMapException {
    	this.config =config;
    	config.put( DS_TYPE, ODBCDSNLessImportAdapter.class.getName() );
    	
        url =(String)config.get( URL );        
        tableName =(String)config.get( TABLE_NAME );
        castString =Boolean.parseBoolean( config.get( CAST_STRING ) );
        useBrackets =Boolean.parseBoolean( config.get( USE_BRACKETS ) );
    }
    
    public void connect() throws TMapException {
        try {
	        // Load the JDBC-ODBC bridge driver
	        Class.forName( JDBC_ODBC_DRIVER_CLASS_NAME ); 
	   
	        // Connect to the database
	        conn = DriverManager.getConnection( url );
        } catch( Exception e ) {
            throw new ImportAdapterException( e );
        }
    }
    
    public void disconnect() {
        try {
            if ( conn != null ) {
                conn.close();
            }
        } catch( Exception e ) {
            // no point to log anything here
        } finally {
            conn =null;
        }
    }
    
    /**
     * 
     */
    @SuppressWarnings("unchecked")
	protected Attrs readValues( int nbRec ) throws ImportAdapterException {
        Exception e2 =null;
        Attrs attrs =null;
        ResultSet rs =null;
        Statement stm =null;
        
        try {
            attrs =(Attrs)boFactory.get( BizObjectFactory.ATTRS );

            List<AttrDef> header =readHeader();
            attrs.setHeader( header );               
                       
            long rowCt =0;
            List<List> rows =new ArrayList<List>();
            attrs.setRows( rows );
            
            StringBuffer sb =new StringBuffer( "select " );
            for( int ct =0; ct < header.size(); ct++ ) {
                AttrDef attrDef =header.get( ct );
                
                if ( StringType.equals( attrDef.getType() ) && castString ) {
                	sb.append( "CAST(")

                	.append( getBracketField( attrDef.getName() ) )
                	                	
                	.append( " AS varchar(")
                	.append( attrDef.getSize() <= VARCHAR_MAX_SIZE ? attrDef.getSize() : VARCHAR_MAX_SIZE )
                	.append( ")) as ")
                	
                	.append( getBracketField( attrDef.getName() ) );
                	
                } else {
                	sb.append( getBracketField( attrDef.getName() ) );
                }
                
                if ( ct < header.size() -1 ) {
                	sb.append( ", " );
                }
            	
            }
            
            sb.append( " from ");
            sb.append( getBracketField( tableName ) );
            
            logger.debug( sb.toString() );
                   
            stm =conn.createStatement();
            rs =stm.executeQuery( sb.toString() );
            
            while( rs.next() ) {
                
                // for sample data
                if ( ( nbRec != -1 ) && ( rowCt >= nbRec ) ) {
                    break;
                }
                
                List<Object> row =new ArrayList<Object>();
                rows.add( row );
                
                for( int ct =0; ct < header.size(); ct++ ) {                   
                    Object value =rs.getObject( ct + 1 );
                    row.add( value );
                }
                
                rowCt++;
            }
                       
            attrs.setDsProperties( config );
        } catch( Exception e ) {
            e2 =e;
        } finally {
            try {
                rs.close();
            } catch (SQLException e1) {
                // nothing to do in that case
            }
            try {
                stm.close();
            } catch (SQLException e3) {
                // nothing to do in that case
            }
        }
        
        if ( e2 != null ) {
            throw new ImportAdapterException( e2 );
        }
             
        return attrs;
    }

}
